package com.dc.util;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class ByteUtils {

    /**
     * 将字符串转成byte数组
     *
     * @param s
     * @return
     * @throws UnsupportedEncodingException
     */
    public static byte[] strToByte(String s) {
        try {
            return s.getBytes("GB2312");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * byte转String
     *
     * @param bytes
     * @return
     */
    public static String byteToStr(byte[] bytes) {
        String license = new String(bytes, Charset.forName("GB2312"));
        return license;
    }

    /**
     * 获取验证码byte数组，基于Modbus CRC16的校验算法
     */
    public static byte[] getCrc16(byte[] arr_buff) {
        int len = arr_buff.length;
        // 预置 1 个 16 位的寄存器为十六进制FFFF, 称此寄存器为 CRC寄存器。
        int crc = 0xFFFF;
        int i, j;
        for (i = 0; i < len; i++) {
            // 把第一个 8 位二进制数据 与 16 位的 CRC寄存器的低 8 位相异或, 把结果放于 CRC寄存器
            crc = ((crc & 0xFF00) | (crc & 0x00FF) ^ (arr_buff[i] & 0xFF));
            for (j = 0; j < 8; j++) {
                // 把 CRC 寄存器的内容右移一位( 朝低位)用 0 填补最高位, 并检查右移后的移出位
                if ((crc & 0x0001) > 0) {
                    // 如果移出位为 1, CRC寄存器与多项式A001进行异或
                    crc = crc >> 1;
                    crc = crc ^ 0xA001;
                } else {
                    // 如果移出位为 0,再次右移一位
                    crc = crc >> 1;
                }

            }
        }
        /**
         * 将int转换成byte数组，低位在前，高位在后
         * 改变高低位顺序只需调换数组序号
         */
        byte[] src = new byte[2];
        src[1] = (byte) ((crc >> 8) & 0xFF);
        src[0] = (byte) (crc & 0xFF);
        return src;
    }

    /**
     * 将int类型的值转成两字节的byte数组
     * 高位在前低位在后
     *
     * @param v
     * @return
     */
    public static byte[] intTo2byteArr(int v) {
        byte[] src = new byte[2];
        src[0] = (byte) ((v >> 8) & 0xFF);
        src[1] = (byte) (v & 0xFF);
        return src;
    }

    /**
     * 十六进制转byte[]数组
     *
     * @param hexStr
     * @return
     */
    public static byte[] hexStr2bytes(String hexStr) {
        if (hexStr.length() % 2 != 0) {//长度为单数
            hexStr = "0" + hexStr;//前面补0
        }
        char[] chars = hexStr.toCharArray();
        int len = chars.length / 2;
        byte[] bytes = new byte[len];
        for (int i = 0; i < len; i++) {
            int x = i * 2;
            bytes[i] = (byte) Integer.parseInt(String.valueOf(new char[]{chars[x], chars[x + 1]}), 16);
        }
        return bytes;
    }

    /**
     * 将byte[]转成list
     *
     * @param bytes
     * @return
     */
    public static List<Byte> ByteToList(byte[] bytes) {
        List list = new ArrayList();
        for (byte b : bytes) {
            list.add(b);
        }
        return list;
    }

    /**
     * 将list转成byte[]
     *
     * @param list
     * @return
     */
    public static byte[] ListToByte(List<Byte> list) {
        if (list == null || list.size() < 0) {
            return null;
        }
        byte[] bytes = new byte[list.size()];
        int i = 0;
        Iterator<Byte> iterator = list.iterator();
        while (iterator.hasNext()) {
            bytes[i] = iterator.next();
            i++;
        }
        return bytes;
    }

    /**
     * 将byte数组转成16进制字符串带空格
     *
     * @param bytes
     * @return
     */
    public static String bytesToHexFun(byte[] bytes) {
        char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5',
                '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        // 一个byte为8位，可用两个十六进制位标识
        char[] buf = new char[bytes.length * 2];
        int a = 0;
        int index = 0;
        for (byte b : bytes) { // 使用除与取余进行转换
            if (b < 0) {
                a = 256 + b;
            } else {
                a = b;
            }
            buf[index++] = HEX_CHAR[a / 16];
            buf[index++] = HEX_CHAR[a % 16];
        }
        String input = new String(buf);
        String regex = "(.{2})";
        input = input.replaceAll(regex, "$1 ");
        return input;
    }

    /**
     * 将byte数组转成16进制字符串不带空格
     *
     * @param bytes
     * @return
     */
    public static String bytesToHexFunNoSpace(byte[] bytes) {
        char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5',
                '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        // 一个byte为8位，可用两个十六进制位标识
        char[] buf = new char[bytes.length * 2];
        int a = 0;
        int index = 0;
        for (byte b : bytes) { // 使用除与取余进行转换
            if (b < 0) {
                a = 256 + b;
            } else {
                a = b;
            }
            buf[index++] = HEX_CHAR[a / 16];
            buf[index++] = HEX_CHAR[a % 16];
        }
        String input = new String(buf);
        return input;
    }

    /**
     * 将byte倒叙
     *
     * @param bytes
     * @return
     */
    public static byte[] flashback(byte[] bytes) {
        List<Byte> list = ByteToList(bytes);
        Collections.reverse(list);
        return ListToByte(list);
    }

    /**
     * 异或校验
     *
     * @param datas
     * @return
     */
    public static byte getXOR(byte[] datas) {
        int temp = 0;
        for (int i = 0; i < datas.length; i++) {
            int preTemp = temp;
            int iData;
            if (datas[i] < 0) {
                iData = datas[i] & 0xff;      // 变为正数计算
            } else {
                iData = datas[i];
            }
            if (temp < 0) {
                temp = temp & 0xff;          // 变为正数
            }
            temp ^= iData;
        }

        return (byte) temp;
    }
    

}

